package com.doge.calcalbum.api

import android.view.View
import androidx.lifecycle.LifecycleOwner
import com.doge.calcalbum.BuildConfig
import com.doge.calcalbum.utils.*
import io.reactivex.Observable
import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers
import okhttp3.Cache
import okhttp3.OkHttpClient
import okhttp3.logging.HttpLoggingInterceptor
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import java.util.concurrent.Executors

private val retrofit: Retrofit
    get() {
        val loggingInterceptor = HttpLoggingInterceptor { log(it, "novel-http") }
        loggingInterceptor.level =
            if (isTestEnv || BuildConfig.DEBUG) HttpLoggingInterceptor.Level.BODY else HttpLoggingInterceptor.Level.NONE

        val builder = OkHttpClient.Builder()
            .addInterceptor(loggingInterceptor)
            .addInterceptor(ReqRespInterceptor())
            .retryOnConnectionFailure(false)
            .cache(Cache(FileUtils.cacheDir("httpCache"), 52428800L))

        val client = builder.build()
        return Retrofit.Builder()
            .addCallAdapterFactory(RxJava2CallAdapterFactory.create())
            .addConverterFactory(GsonConverterFactory.create())
            .baseUrl(serviceUrl)
            .client(client)
            .build()
    }

val api by lazy { retrofit.create(ApiService::class.java) }

private val workExecutor by lazy { Executors.newSingleThreadExecutor()!! }
val workScheduler = Schedulers.from(workExecutor)

fun <T> Observable<T>.subscribeOnIO(): Observable<T> = subscribeOn(Schedulers.io())
fun <T> Observable<T>.observeOnMain(): Observable<T> = observeOn(AndroidSchedulers.mainThread())

fun Disposable.bindLifecycle(owner: LifecycleOwner?) = this.apply {
    val lifecycle = owner?.lifecycle
    lifecycle?.let { it.addObserver(LifecycleObserver(it, this)) }
}

fun Disposable.bindLifecycle(view: View?) =
    this.apply {
        val lifecycle = view?.lifecycleOwner?.lifecycle
        lifecycle?.let { it.addObserver(LifecycleObserver(it, this)) }
    }
